<?php
namespace App\Di;

class Di implements \ArrayAccess
{
    protected $_service = [];
    protected $_sharedService = [];

    public function offsetExists ($offset)
    {
    }

    public function offsetGet ($offset)
    {
    }

    public function offsetSet ($offset, $value)
    {
    }

    public function offsetUnset ($offset)
    {
    }

    public function set ($name, $definition)
    {
        $this->registerService($name, $definition);
    }

    public function setShared ($name, $definition)
    {
        $this->registerService($name, $definition, true);
    }

    private function registerService ($name, $definition, $shared = false)
    {
        $this->remove($name);
        if (!($definition instanceof \Closure) && is_object($definition) && $shared == true)
        {
            $this->_sharedService[$name] = $definition;
        }
        else
        {
            $this->_service[$name] = $definition;
        }
    }

    private function remove ($name)
    {
        unset($this->_service[$name], $this->_sharedService[$name]);
    }

    public function get ($name, $params = [])
    {
        if (isset($this->_sharedService[$name]))
        {
            return $this->_sharedService[$name];
        }
        if (!isset($this->_service[$name]))
        {
            throw new \Exception("Service '" . $name . "' wasn't found in the dependency injection container");
        }
        $service  = $this->_service[$name];
        $instance = null;
        //匿名函数方式
        if ($service instanceof \Closure)
        {
            $instance = call_user_func_array($service, $params);
        }
        else if (is_string($service))
        {
            if (empty($params))
            {
                $instance = new $service;
            }
            else
            {
                $class    = new \ReflectionClass($service);
                $instance = $class->newInstanceArgs($params);
            }
        }
        return $instance;
    }
}